(* Release 3.00 *)

(*    c_signal -  signal module *)

(*    Copyright (C) 1989 Jensen and Partners. All Rights Reserved*)
(*    Written by Simon Knight.*)

(*    Copyright (C) 1991 Psion PLC. All Rights Reserved*)
(*    Modified by NSM.*)

include "corelib.inc"
include "epocdefs.inc"

module csignal

(***************************************************************************)
segment _BSS(BSS, 28H)

public CoreSig@CnsHandler :  org CodePtrSize

segment _BSS(BSS, 28H)

public __sigTable :  org 46

segment _BSS(BSS, 28H)

public @RecursiveExit : org 2

segment _BSS(BSS, 28H)

public _errno :      org 2

(***************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA, 28H)

extrn _errno

select _TEXT

public __seterrno :

    mov  [_errno], ax
    ret  0

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA, 28H)

extrn _errno

select _TEXT

public __errno__ :

    mov  ax, _errno
    ret  0

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA, 28H)

extrn _errno
extrn __doserrno

validError:
	db	  0, -1, -2, -5, -6, -7, -9
	db	-10,-15,-16,-18,-32,-33,-36
	db	-37,-39,-40,-41,-42,-66,  1
    
select _TEXT

public __ioerr :

    cbw
    mov  [__doserrno], ax
    push bx
    cmp	 ax, -128
    jl	 invalid
    cmp	 ax, 0
    jg	 invalid
    mov	 bx, validError
locateLoop:
    cmp	 [bx], al
    je	 errorOk
    inc	 bx
    cmp	 byte [bx], 1
    jne	 locateLoop
invalid:
    mov	 ax, EFAULT
errorOk:
    pop	 bx
    mov  [_errno], ax
    ret  0

    dw __doserrno


(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA, 28H)

select _TEXT   (* must be in TEXT *)

extrn __FloatJmpSave
extrn __FloatJmpRestore
extrn _DatClassHandle
extrn _DatClassPtr
extrn _DatEnterFramePtr
extrn _DatOsFramePtr

public _setjmp :
public __setjmp :
(*
int setjmp(jmp_buf task_state)
Saves current task state and returns 0.
*)
    push bp
    mov  bp, sp
    push di
    mov  di, ax
    call __FloatJmpSave
    pushf
    pop	 ax
    stosw
    mov  ax, [bp][2]
    stosw
    lea  ax, [bp][4]
    stosw
    mov  ax, [bp]
    stosw
    mov	 ax, si
    stosw
    mov	 ax, [bp][-2]
    stosw
    mov	 ax, dx
    stosw
    mov	 ax, cx
    stosw
    mov	 ax, bx
    stosw
    mov	 ax,[_DatClassHandle]
    stosw
    mov	 ax,[_DatClassPtr]
    stosw
    mov	 ax,[_DatEnterFramePtr]
    stosw
    mov	 ax,[_DatOsFramePtr]
    stosw
    sub  ax, ax
    pop  di
    pop  bp
    ret  0

(* _setjmp ENDP *)

public _longjmp :
(*
void longjmp ( task_state, val);
Restores task state and jumps to landing_zone.
Returns val. (If val == 0, val++)
*)

    mov  si, ax
    cmp  bx, 1	                (* generates carry if BX = 0 *)
    adc  bx, 0                  (* (val) BX = (BX) ? BX : 1; *)
    call __FloatJmpRestore
    mov  di, [si][_j_di]
    mov  dx, [si][_j_dx]
    mov  cx, [si][_j_cx]
    mov	 ax, [si][_j_classHandle]
    mov	 [_DatClassHandle], ax
    mov	 ax, [si][_j_classPtr]
    mov	 [_DatClassPtr], ax
    mov	 ax, [si][_j_enterFrame]
    mov	 [_DatEnterFramePtr], ax
    cli
    mov  sp, [si][_j_sp]
    mov  bp, [si][_j_bp]
    mov	 ax, [si][_j_osFrame]
    mov	 [_DatOsFramePtr], ax
    push [si][_j_flag]
    popf
    push [si][_j_ip]
    mov  ax, bx
    mov  bx, [si][_j_bx]
    mov  si, [si][_j_si]
    ret  0

(* _longjmp ENDP  *)

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA,28H)

select _DATA

HeadMsg : db 'Process Terminated', 0

select _TEXT

public __sysmsg :
    mov	 bx, HeadMsg
    mov	 cx, ax
    sub	 dx, dx
    mov	 di, dx
    mov  si, dx
    mov	 ah, NmGenNotify
    int	 GenManager
    ret	 0

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _INIT(DATA,28H)
segment _DATA(DATA,28H)

extrn __initsig
extrn __InitLoop

select _TEXT

do_initsig : (* defined later on ! *)

select _INIT
initsig : dw MAGIC
    	  db PR3
          dw do_initsig

select _DATA
public __NSIG :  dw  22, initsig

select  _TEXT

    call __initsig
    jmp  __InitLoop

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA,28H)
segment _BSS(BSS,28H)

extrn __FatalError
extrn __FatalErrorPos
extrn __table_raise

select _BSS

extrn __sigTable
                                    SIGINT  = 2
                                    SIGILL  = 8
                                    SIGFPE  = 16
                                    SIGSEGV = 22
                                    SIGTERM = 30
                                    SIGUSR1 = 32
                                    SIGUSR2 = 34
                                    SIGUSR3 = 40
                                    SIGABRT = 44

select _DATA

DefMsg : db 'By Signal', 0
FpeMsg : db 'By Floating Point Exception', 0
Usr1Msg : db 'By User 1 Signal', 0
Usr2Msg : db 'By User 2 Signal', 0
Usr3Msg : db 'By User 3 Signal', 0
AbrtMsg : db 'By Abort', 0

extrn __sigsetup
extrn  __exitsig
extrn  __sysmsg
extrn  __FloatMathExcepDos
extrn  __NSIG
extrn __SH_sword
extrn __exc_addr

select _TEXT

SIG_ERR = -1
SIG_DFL =  0
SIG_IGN =  1

__do_exitsig :

    ret  0

public __initsig :

                                  (* set up handler table *)
    cmp  word [__sigsetup], 0
    jnz  near noInit
    not  word [__sigsetup]
    mov  bx, __sigTable
    mov  word [__exitsig], __do_exitsig
    mov  ax, SIG_DFL
    mov  [bx][SIGABRT], ax        (* SIGABRT *)
    mov  [bx][SIGILL], ax         (* SIGILL *)
    mov  [bx][SIGSEGV], ax        (* SIGSEGV *)
    mov  [bx][SIGINT], ax         (* SIGINT *)
    mov  [bx][SIGFPE], ax         (* SIGFPE *)
    mov  [bx][SIGTERM], ax        (* SIGTERM *)
    mov  [bx][SIGUSR1], ax        (* SIGUSR1 *)
    mov  [bx][SIGUSR2], ax        (* SIGUSR2 *)
    mov  [bx][SIGUSR3], ax        (* SIGUSR3 *)

noInit:
    ret  0

public __sigIgnore :

(* A signal is ignored by doing nothing. *)

    ret  0

public __sigDefault :

(* Default action when a signal occurs is to exit the program. *)

    push ax
    cmp  ax, 8
    je   typeFPE
    cmp	 ax, 16
    je	 typeUsr1
    cmp	 ax, 17
    je	 typeUsr2
    cmp	 ax, 20
    je	 typeUsr3
    cmp  ax, 22
    je   typeABRT
typeDEFAULT:
    mov  ax, DefMsg
    jmp  sendMessage
typeFPE:
    mov  ax, FpeMsg
    jmp  sendMessage
typeUsr1:
    mov	 ax, Usr1Msg
    jmp	 sendMessage
typeUsr2:
    mov	 ax, Usr2Msg
    jmp	 sendMessage
typeUsr3:
    mov	 ax, Usr3Msg
    jmp	 sendMessage
typeABRT:
    mov  ax, AbrtMsg

sendMessage:
    call __sysmsg
    call __FatalErrorPos
    pop  cx
    mov  bx, FatalSignal
    cmp  cx, 8
    jne  notFP
    mov  ax, [__exc_addr]
notFP:
    jmp  __FatalError

public __sigFp :
    call __FloatMathExcepDos
    push ax
    push bx
    push cx
    push dx
    push di
    push si
    mov  bx, SIGFPE
    mov  ax, [__SH_sword]
    mov  cx, 8
transLoop:
    shr  ax, 1
    jc   foundBit
    loop transLoop
foundBit:
    mov  ax, 89H
    sub  ax, cx
    call __table_raise
    pop  si
    pop  di
    pop  dx
    pop  cx
    pop  bx
    pop  ax
    ret  0

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA,28H)
segment _BSS(BSS,28H)

extrn __NSIG
extrn __sigTable
extrn __sigIgnore
extrn __sigDefault
extrn __seterrno

select _TEXT

public _signal :
(*
void ( *signal(int sig, void ( * func)()))();
sets signal handler to func.
Returns old function pointer.
*)

EINVAL = 19

    push bx
    push cx

    mov  cx, bx
    mov  bx, ax
    or   bx, bx
    je   sigErr
    cmp  bx, [__NSIG]
    ja   sigErr
    shl  bx, 1                   (* calculate table index *)
    add  bx, __sigTable
    mov  ax, [bx]
    mov  [bx], cx                (* store new function pointer *)
sigDone:
    pop  cx
    pop  bx
    ret  0
sigErr:
    mov  ax, EINVAL
    call __seterrno
    mov  ax, -1
    jmp  sigDone

public _raise :
(*
int raise(sig);
raises signal.
*)

    push bx
    push cx
    mov	 cx, bx
    mov  bx, ax
    or   bx, bx
    je   raiseErr
    cmp  bx, [__NSIG]
    ja   raiseErr
    shl  bx, 1                    (* calculate table index *)
    mov  ax, cx
    call __table_raise
    sub  ax, ax
raiseDone:
    pop  cx
    pop  bx
    ret  0
raiseErr:                         (* return -1 *)
    mov  ax, -1
    jmp  raiseDone

SIG_DFL =  0
SIG_IGN =  1

SIGINT  = 2
SIGILL  = 8
SIGFPE  = 16
SIGSEGV = 22
SIGTERM = 30
SIGUSR1 = 32
SIGUSR2 = 34
SIGUSR3 = 40
SIGABRT = 44

public __table_raise :   (* bx = sig num offset, ax = arg *)

    push bx
    push cx
    push dx
    mov  dx, ax
    mov  ax, bx
    shr  ax, 1
    mov  cx, [bx][__sigTable]
    cmp  bx, SIGTERM
    je   doDFL
    cmp  bx, SIGABRT
    je   doDFL
    cmp  bx, SIGILL
    je   doDFL
    cmp  bx, SIGSEGV
    je   doDFL
    cmp  bx, SIGINT
    je   doDFL
    cmp  bx, SIGFPE
    je   doDFL
    cmp  bx, SIGUSR1
    je   doDFL
    cmp  bx, SIGUSR2
    je   doDFL
    cmp  bx, SIGUSR3
    jne  dontSet
doDFL:
    mov  word [bx][__sigTable], SIG_DFL
dontSet:
    cmp	 cx, 1
    jbe	 defRaise
    mov  bx, dx
    call cx
trDone:
    pop  dx
    pop  cx
    pop  bx
    ret  0

defRaise:
    jcxz callDefault
    call __sigIgnore
    jmp  trDone
callDefault:
    call __sigDefault
    jmp  trDone

end
